//
// Created by zjs on 19-12-9.
//

#ifndef BRFD_C_WAYBILLNBCHECK_H
#define BRFD_C_WAYBILLNBCHECK_H

#include <regex>
#include <string>

using namespace std;

// 12位运单号截取前4位的号段代码列表
static vector<string> NS_CODE_SPLIT_4 = {"9550", "9551", "9552", "9553", "9554", "9555", "9556", "9557", "9558", "162", "486", "863",
                                  "788", "708", "785"};
//12位运单号截取前5位的号段代码列表
static vector<string> NS_CODE_SPLIT_5 = {"9559"};
// 12位运单号截取前7位的号段代码列表
static vector<string> NS_CODE_SPLIT_7 = {"36000"};
// 8位袋号号段代码列表
static vector<string> POCKET_NS_CODE = {"696", "709", "SFE"};

// 12位运单号号段类型集合
static vector<string> NS_CODE_OF_WAYBILL_TYPE = {"000", "001", "002", "003", "004", "005", "006", "007", "008", "009", "010", "011",
                                          "012", "013", "014", "015", "016", "017", "018", "019", "020", "021", "022", "023",
                                          "024", "025", "026", "027", "028", "029", "030", "031", "032", "033", "034", "035",
                                          "036", "037", "038", "039", "040", "041", "042", "043", "044", "045", "046", "047",
                                          "048", "049", "050", "051", "052", "053", "054", "055", "056", "057", "058", "059",
                                          "060", "061", "062", "063", "065", "066", "067", "068", "069", "070", "071", "072",
                                          "073", "074", "075", "076", "077", "078", "079", "080", "081", "082", "083", "084",
                                          "085", "086", "087", "088", "089", "090", "091", "092", "093", "094", "095", "096",
                                          "097", "098", "099", "100", "101", "102", "103", "104", "105", "106", "107", "108",
                                          "109", "110", "112", "113", "114", "115", "116", "117", "118", "119", "120", "123",
                                          "131", "132", "133", "134", "139", "150", "151", "152", "153", "155", "156", "157",
                                          "158", "159", "160", "161", "1620", "1621", "1622", "1623", "1624", "1625", "1626",
                                          "1627", "1628", "1629", "163", "164", "165", "166", "167", "168", "169", "170", "171",
                                          "172", "173", "174", "175", "176", "177", "178", "179", "180", "181", "182", "183",
                                          "184", "185", "186", "187", "188", "189", "190", "191", "192", "193", "194", "195",
                                          "196", "197", "198", "199", "200", "201", "202", "203", "204", "205", "206", "207",
                                          "208", "209", "210", "211", "212", "213", "214", "215", "216", "217", "218", "219",
                                          "220", "221", "227", "228", "229", "230", "231", "232", "233", "234", "235", "236",
                                          "237", "238", "239", "240", "241", "242", "243", "244", "245", "246", "247", "248",
                                          "249", "250", "251", "252", "253", "254", "255", "256", "257", "258", "259", "260",
                                          "261", "262", "263", "264", "265", "266", "267", "268", "269", "270", "271", "272",
                                          "273", "274", "275", "276", "277", "278", "279", "280", "281", "282", "283", "284",
                                          "285", "286", "287", "288", "289", "290", "291", "292", "293", "294", "295", "296",
                                          "297", "298", "299", "300", "301", "302", "304", "305", "306", "307", "308", "309",
                                          "310", "311", "312", "313", "314", "315", "316", "317", "318", "319", "320", "321",
                                          "322", "323", "324", "325", "326", "327", "328", "329", "330", "331", "332", "335",
                                          "348", "349", "351", "352", "353", "354", "355", "356", "357", "358", "359", "3600000",
                                          "3600001", "3600002", "3600003", "3600004", "3600005", "3600006", "3600007", "3600008",
                                          "3600009", "3600010", "3600011", "3600012", "3600013", "3600014", "3600015", "3600016",
                                          "3600017", "3600018", "3600019", "3600020", "3600021", "3600022", "3600023", "3600024",
                                          "3600025", "3600026", "3600027", "3600028", "3600029", "361", "362", "363", "364", "365",
                                          "366", "367", "368", "369", "370", "371", "372", "373", "374", "375", "376", "377",
                                          "378", "379", "380", "382", "383", "384", "385", "386", "387", "388", "389", "390",
                                          "391", "392", "393", "394", "395", "396", "398", "400", "401", "403", "404", "405",
                                          "406", "407", "408", "409", "410", "411", "412", "413", "414", "415", "416", "417",
                                          "418", "419", "420", "421", "422", "423", "424", "425", "426", "427", "428", "429",
                                          "431", "432", "433", "434", "435", "436", "437", "438", "439", "440", "441", "442",
                                          "443", "444", "445", "446", "447", "448", "449", "450", "451", "452", "453", "454",
                                          "455", "456", "457", "458", "459", "460", "461", "462", "463", "464", "465", "466",
                                          "467", "468", "469", "470", "471", "472", "473", "474", "475", "476", "477", "478",
                                          "479", "480", "481", "482", "483", "484", "485", "4860", "4861", "4862", "4863", "4864",
                                          "4865", "4866", "4867", "4868", "4869", "487", "488", "489", "490", "491", "492", "493",
                                          "494", "495", "496", "497", "498", "499", "500", "501", "502", "503", "504", "505",
                                          "506", "507", "508", "509", "510", "511", "512", "513", "514", "515", "516", "517",
                                          "518", "519", "520", "521", "522", "523", "524", "525", "526", "527", "528", "529",
                                          "530", "531", "532", "533", "534", "535", "536", "537", "538", "539", "540", "541",
                                          "542", "543", "544", "545", "546", "547", "548", "549", "550", "551", "552", "553",
                                          "554", "555", "556", "557", "558", "559", "560", "561", "562", "563", "564", "565",
                                          "566", "567", "568", "569", "570", "571", "572", "573", "574", "575", "576", "577",
                                          "578", "579", "580", "581", "582", "583", "584", "585", "586", "587", "588", "589",
                                          "590", "591", "592", "593", "594", "595", "596", "597", "598", "599", "600", "601",
                                          "602", "603", "604", "605", "606", "607", "608", "609", "610", "611", "612", "613",
                                          "614", "615", "616", "617", "618", "619", "620", "621", "622", "623", "624", "625",
                                          "626", "627", "628", "629", "630", "631", "632", "633", "634", "635", "636", "637",
                                          "638", "639", "640", "641", "642", "643", "644", "645", "646", "647", "648", "649",
                                          "650", "651", "652", "653", "654", "655", "656", "657", "658", "659", "660", "661",
                                          "662", "663", "664", "665", "666", "667", "668", "669", "670", "671", "672", "673",
                                          "674", "675", "676", "677", "678", "682", "683", "684", "685", "686", "687", "688",
                                          "689", "690", "691", "692", "693", "694", "695", "697", "698", "699", "700", "701",
                                          "702", "703", "704", "705", "706", "707", "7080", "7081", "7082", "7083", "7084", "7085",
                                          "7086", "7087", "7088", "7089", "710", "711", "712", "713", "714", "715", "716", "717",
                                          "718", "719", "720", "721", "722", "723", "724", "725", "726", "727", "728", "729",
                                          "730", "731", "732", "733", "734", "735", "736", "737", "738", "739", "740", "741",
                                          "742", "743", "744", "745", "746", "747", "748", "749", "750", "751", "752", "753",
                                          "754", "755", "756", "757", "758", "759", "760", "761", "762", "763", "764", "765",
                                          "766", "767", "768", "769", "770", "771", "772", "773", "774", "775", "776", "777",
                                          "778", "779", "780", "781", "782", "783", "784", "785", "7850", "7851", "7852", "7853",
                                          "7854", "7855", "7856", "7857", "7858", "7859", "786", "787", "7880", "7881", "7882",
                                          "7883", "7884", "7885", "7886", "7887", "7888", "7889", "789", "790", "791", "792",
                                          "793", "794", "795", "796", "797", "798", "799", "800", "801", "802", "803", "804",
                                          "808", "809", "810", "811", "812", "813", "814", "815", "816", "817", "818", "819",
                                          "820", "821", "823", "824", "825", "826", "827", "828", "829", "830", "831", "832",
                                          "833", "834", "835", "836", "837", "838", "839", "841", "842", "843", "844", "845",
                                          "846", "847", "848", "849", "850", "851", "852", "853", "854", "855", "856", "857",
                                          "858", "859", "860", "861", "862", "8630", "8631", "8632", "8633", "8634", "8635",
                                          "8636", "8637", "8638", "8639", "864", "865", "866", "868", "869", "870", "871", "872",
                                          "873", "874", "875", "876", "877", "878", "879", "880", "881", "882", "884", "885",
                                          "886", "887", "888", "889", "891", "893", "894", "895", "896", "897", "898", "899",
                                          "900", "901", "902", "903", "904", "905", "906", "907", "908", "909", "910", "911",
                                          "912", "913", "914", "916", "917", "918", "919", "920", "921", "922", "923", "924",
                                          "925", "926", "927", "928", "929", "930", "931", "932", "933", "934", "950", "951",
                                          "952", "953", "954", "9550", "9551", "9552", "9553", "9554", "9555", "9556", "9557",
                                          "9558", "956", "957", "958", "959", "960", "961", "962", "963", "964", "965", "966",
                                          "969", "971", "972", "973", "974", "975", "976", "978", "979", "990", "991", "992",
                                          "993", "994", "995", "996", "997", "998", "999"};

// 通用12位运单号校验码规则
static const map<int, int> DEFAULT_RULE_12 = {{3, 15}, {4, 13}, {5, 11}, {6, 9}, {7, 7}, {8, 5}, {9, 3}, {10, 1}};
// 通用15位运单号校验码规则
static const map<int, int> DEFAULT_RULE_15 = {{5, 17}, {6, 15}, {7, 13}, {8, 11}, {9, 9}, {10, 7}, {11, 5}, {12, 3}, {13, 1}};
// 苹果件15位运单号校验码规则
static const map<int, int> APPLE_RULE = {{5, 11}, {6, 9}, {7, 7}, {8, 5}, {9, 3}, {10, 1}};
// 亚马逊15位运单号校验码规则
static const map<int, int> AMAZON_RULE = {{8, 11}, {9, 9}, {10, 7}, {11, 5}, {12, 3}, {13, 1}};
// MOMO件15位运单号校验码规则
static const map<int, int> MOMO_RULE = {{8, 12}, {9, 10}, {10, 8}, {11, 6}, {12, 4}, {13, 2}};

// 15位特殊号段校验码规则映射
static const map<string, map<int, int>> SP_NS_CODE_RULE_MAPPING = {{"SF960", APPLE_RULE}, {"SF70090", APPLE_RULE},
                                                            {"SF70091", APPLE_RULE}, {"SF70092", APPLE_RULE},
                                                            {"SF70093", APPLE_RULE}, {"SF70094", APPLE_RULE},
                                                            {"SF70095", APPLE_RULE}, {"SF70096", APPLE_RULE},
                                                            {"SF70097", APPLE_RULE}, {"SF70098", APPLE_RULE},
                                                            {"SF70099", APPLE_RULE}, {"SF6310", AMAZON_RULE},
                                                            {"SF70024", MOMO_RULE}};


// 对运单号校验位进行合法性校验
inline  bool __check_code(const string& waybill_nb, map<int, int> rule)
{
  int q = 0;

  for (auto iter: rule){
    char temp = waybill_nb.c_str()[iter.first];
    int ttemp;
    stringstream ss;
    ss << temp;
    ss >> ttemp;
    int p = ttemp * iter.second;
    q += p / 10 + (p - 10 * (p / 10));
  }
  int m = (q / 10 + 1) * 10;
  m = m - q - 10 * ((m - q) / 10);

  return to_string(m)[0] == waybill_nb[waybill_nb.size() - 1];
}


// 获取15位运单号的号段代码
inline string __find_ns_code_15(const std::string& waybill_nb)
{
  if (waybill_nb.substr(0, 3) == "SF7")
    return waybill_nb.substr(0, 7);
  else if (waybill_nb.substr(0, 3) == "SF6")
    return waybill_nb.substr(0, 6);
  else if (waybill_nb.substr(0, 2) == "SF")
    return waybill_nb.substr(0, 5);
  else
    return "";
}

// 校验15为号码
inline bool __valid_waybill_nb_15(const std::string& waybill_nb, const string& ns_code)
{
  map<int, int> rule;
  auto it = SP_NS_CODE_RULE_MAPPING.find(ns_code);

  if (it != SP_NS_CODE_RULE_MAPPING.end()){
    rule = SP_NS_CODE_RULE_MAPPING.find(ns_code)->second;
  }else{
    rule = DEFAULT_RULE_15;
  }

  return __check_code(waybill_nb, rule);
}


inline bool _is_waybill_nb_15(const std::string& waybill_nb)
{
  std::regex reg("^SF\\d{13}$");
  if (std::regex_match(waybill_nb, reg))
  {
    string ns_code = __find_ns_code_15(waybill_nb);
    if (ns_code.empty())
      return false;
    return __valid_waybill_nb_15(waybill_nb, ns_code);
  }


  return 0;
}

// 获取12位运单号的号段代码
inline string __find_ns_code_12(const std::string& waybill_nb)
{
  string prefix3 = waybill_nb.substr(0, 3);
  string prefix4 = waybill_nb.substr(0, 4);
  string prefix5 = waybill_nb.substr(0, 5);

  auto result_3 = find(NS_CODE_SPLIT_4.begin( ), NS_CODE_SPLIT_4.end( ), prefix3);
  auto result_4 = find(NS_CODE_SPLIT_4.begin( ), NS_CODE_SPLIT_4.end( ), prefix4);
  if ( result_3 != NS_CODE_SPLIT_4.end( ) || result_4 != NS_CODE_SPLIT_4.end())
    return waybill_nb.substr(0, 4);

  auto result_5 = find(NS_CODE_SPLIT_5.begin( ), NS_CODE_SPLIT_5.end( ), prefix4);
  if ( result_5 != NS_CODE_SPLIT_5.end( ))
    return waybill_nb.substr(0, 5);

  auto result_7 = find(NS_CODE_SPLIT_7.begin( ), NS_CODE_SPLIT_7.end( ), prefix5);
  if ( result_7 != NS_CODE_SPLIT_7.end( ))
    return waybill_nb.substr(0, 7);

  return waybill_nb.substr(0, 3);
}

inline bool _is_waybill_nb_12(const std::string& waybill_nb)
{
  std::regex reg("^\\d{12}$");
  if (std::regex_match(waybill_nb, reg))
  {
    string ns_code = __find_ns_code_12(waybill_nb);

    auto result = find( NS_CODE_OF_WAYBILL_TYPE.begin( ), NS_CODE_OF_WAYBILL_TYPE.end( ), ns_code);
    if ( result != NS_CODE_OF_WAYBILL_TYPE.end( ))
      return __check_code(waybill_nb, DEFAULT_RULE_12);

    return false;
  }

  return false;
}

inline bool waybill_nb_check(const std::string& waybill_nb)
{
  if (waybill_nb.size() == 15)
    return _is_waybill_nb_15(waybill_nb);
  else if (waybill_nb.size() == 12)
    return _is_waybill_nb_12(waybill_nb);
  else
    return false;
}

#endif //BRFD_C_WAYBILLNBCHECK_H

